package tests;

import lexer.Token;
import lexer.TokenType;

import org.junit.*;


/**
 * Test class that tests the basic functions of the lexer
 * Test is using JUnit 4
 * @author sebastian
 *
 */

public class LexerTest {
	
	@Test(timeout = TestUtil.DEFAULT_TIMEOUT)
    public void testIdentiferBasicLexerFunction() throws Exception {
        TestUtil.testLexer("hallo", new Token(0, 0, TokenType.IDENT, "hallo"),
        						new Token(0, 0, TokenType.EOF, ""));
        TestUtil.testLexer("_hal_l_o_10_", new Token(0, 0, TokenType.IDENT, "_hal_l_o_10_"),
				new Token(0, 0, TokenType.EOF, ""));
    }
	
	@Test(timeout = TestUtil.DEFAULT_TIMEOUT)
    public void testLiteralBasicLexerFunction() throws Exception {
		TestUtil.testLexer("123", new Token(0, 0, TokenType.INT_LITERAL, "123"),
				new Token(0, 0, TokenType.EOF, ""));
		TestUtil.testLexer("123L", new Token(0, 0, TokenType.LONG_LITERAL, "123L"),
				new Token(0, 0, TokenType.EOF, ""));
		TestUtil.testLexer("123.00979", new Token(0, 0, TokenType.DOUBLE_LITERAL, "123.00979"),
				new Token(0, 0, TokenType.EOF, ""));
		TestUtil.testLexer("123.088f", new Token(0, 0, TokenType.FLOAT_LITERAL, "123.088f"),
				new Token(0, 0, TokenType.EOF, ""));
		TestUtil.testLexer("123.", new Token(0, 0, TokenType.DOUBLE_LITERAL, "123.0"),
				new Token(0, 0, TokenType.EOF, ""));	
		TestUtil.testLexer("'a' abc", new Token(0, 0, TokenType.CHAR_LITERAL, "a"),
				new Token(0, 0, TokenType.IDENT, "abc"),
				new Token(0, 0, TokenType.EOF, ""));
		TestUtil.testLexer("\"a\" abc", new Token(0, 0, TokenType.STRING_LITERAL, "a"),
				new Token(0, 0, TokenType.IDENT, "abc"),
				new Token(0, 0, TokenType.EOF, ""));
    }
	
	@Test(timeout = TestUtil.DEFAULT_TIMEOUT)
    public void testCommentsBasicLexerFunction() throws Exception {
		TestUtil.testLexer("/+ /+ /+ ident +/123+/peace+/ ", new Token(0, 0, TokenType.EOF, ""));
		TestUtil.testLexer("#hallo \n peace", new Token(0, 0, TokenType.IDENT, "peace"),
				new Token(0, 0, TokenType.EOF, ""));
    }
	
	@Test(timeout = TestUtil.DEFAULT_TIMEOUT)
    public void testOperatorBasicLexerFunction() throws Exception {
		TestUtil.testLexer("++-- \n ", new Token(0, 0, TokenType.INCREMENT, ""),
				new Token(0, 0, TokenType.DECREMENT, ""),
				new Token(0, 0, TokenType.EOF, ""));
    }
	
	@Test(timeout = TestUtil.DEFAULT_TIMEOUT)
    public void testSeperatorBasicLexerFunction() throws Exception {
		TestUtil.testLexer("; ; ; ", new Token(0, 0, TokenType.SEMI, ""),
				new Token(0, 0, TokenType.SEMI, ""),
				new Token(0, 0, TokenType.SEMI, ""),
				new Token(0, 0, TokenType.EOF, ""));
    }
	
	@Test(timeout = TestUtil.DEFAULT_TIMEOUT)
    public void testEscapeCharacterBasicLexerFunction() throws Exception {
		TestUtil.testLexer("\'\\t\'", new Token(0, 0, TokenType.CHAR_LITERAL, "\\t"), 
				new Token(0, 0, TokenType.EOF, ""));
		TestUtil.testLexer("\'\\n\'", new Token(0, 0, TokenType.CHAR_LITERAL, "\\n"), 
				new Token(0, 0, TokenType.EOF, ""));
		TestUtil.testLexer("\"\\t\"", new Token(0, 0, TokenType.STRING_LITERAL, "\\t"), 
				new Token(0, 0, TokenType.EOF, ""));
		TestUtil.testLexer("\"\\a\"", new Token(0, 0, TokenType.STRING_LITERAL, "\\a"), 
				new Token(0, 0, TokenType.EOF, ""));
		TestUtil.testLexer("\'\\\'\'", new Token(0, 0, TokenType.CHAR_LITERAL, "\\\'"), 
				new Token(0, 0, TokenType.EOF, ""));
		TestUtil.testLexer("\"\\\"\"", new Token(0, 0, TokenType.STRING_LITERAL, "\\\""), 
				new Token(0, 0, TokenType.EOF, ""));
    }
	
	@Test(timeout = TestUtil.DEFAULT_TIMEOUT)
	public void testLLVMinlining() throws Exception {
		TestUtil.testLexerOnlyTokenTypes("llvm{ hallo pieps test }llvm", TokenType.LLVMSTART,
				TokenType.LLVMCODE, TokenType.LLVMEND);
		TestUtil.testLexerOnlyTokenTypes("llvmdecl{ pieps declaration LLVM }llvmdecl", 
				TokenType.LLVMDECLSTART, TokenType.LLVMCODE, TokenType.LLVMDECLEND);
		TestUtil.testLexerOnlyTokenTypes("llvm{ und ohen Ende? %&/(", 
				TokenType.LLVMSTART, TokenType.LLVMCODE);
	}
	
	@Test(timeout = TestUtil.DEFAULT_TIMEOUT)
	public void testTemplates() throws Exception {
		TestUtil.testLexerOnlyTokenTypes("template<!T!> test { }", TokenType.TEMPLATE,
				TokenType.GENERICSTART, TokenType.IDENT, TokenType.GENERICEND,
				TokenType.IDENT, TokenType.LBRACE, TokenType.RBRACE);
	}
}
